package com.test.qpbgboot.show.service.impl;

import com.test.qpbgboot.base.enums.EnumController;
import com.test.qpbgboot.base.exception.ServiceException;
import com.test.qpbgboot.base.response.ResultStatus;
import com.test.qpbgboot.show.mapper.TagMapper;
import com.test.qpbgboot.show.pojo.dto.TagQuery;
import com.test.qpbgboot.show.pojo.dto.TagSaveParam;
import com.test.qpbgboot.show.pojo.entity.Tag;
import com.test.qpbgboot.show.pojo.vo.TagVO;
import com.test.qpbgboot.show.service.TagService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class TagServiceImpl implements TagService {

    @Autowired
    private TagMapper tagMapper;

    @Override
    public List<TagVO> tagSelect(TagQuery tagQuery) {
        log.debug("标签查询业务，参数:{}", tagQuery);
        List<TagVO> tagVOList = tagMapper.selectTagVOByTagQuery(tagQuery);
        if (tagVOList != null && !tagVOList.isEmpty()) {
            Set<Long> idSet = tagVOList.stream().map(TagVO::getId).collect(Collectors.toSet());
            List<TagVO> tagVOListCopy = new ArrayList<>(tagVOList);
            Set<Long> idSetCopy = new HashSet<>(idSet);
            if (tagQuery.getRecursionUp() != null && tagQuery.getRecursionUp()) {
                upRecursion(tagVOList, idSet, 0);
            }
            if (tagQuery.getRecursionDown() != null && tagQuery.getRecursionDown()) {
                downRecursion(tagVOListCopy, idSetCopy, 0);
            }
            addTagVO(tagVOList, idSet, tagVOListCopy);
        }
        log.debug("标签查询结果:{}", tagVOList);
        return tagVOList;
    }

    @Override
    public List<TagVO> tagSelectByIdList(List<Long> tagIdList) {
        log.debug("标签查询-根据id列表-业务，参数:tagIdList={}", tagIdList);
        List<TagVO> tagVOList = tagMapper.selectTagVOByTagIdList(tagIdList);
        log.debug("标签查询-根据id列表-结果:{}", tagVOList);
        return tagVOList;
    }

    @Override
    public void tagSave(TagSaveParam tagSaveParam) {
        log.debug("标签保存业务，参数:{}", tagSaveParam);
        if (!EnumController.checkContain(tagSaveParam.getType(), "TagType")) {
            throw new ServiceException(ResultStatus.ILLEGAL_ARGUMENT);
        }
        Tag tag = new Tag();
        BeanUtils.copyProperties(tagSaveParam, tag);

        TagQuery tagQuery = new TagQuery();
        BeanUtils.copyProperties(tag, tagQuery);
        tagQuery.setId(null);
        List<TagVO> tagVOList = tagMapper.selectTagVOByTagQuery(tagQuery);
        if (tagVOList != null && !tagVOList.isEmpty()
                && !tagVOList.get(0).getId().equals(tag.getId())) {
            throw new ServiceException(ResultStatus.OBJECT_ALREADY_EXISTS);
        }
        if (tagSaveParam.getId() == null) {
            tagMapper.insert(tag);
        } else {
            tagMapper.update(tag);
        }
    }

    @Override
    public void tagDelete(Long id) {
        log.debug("标签删除业务，参数:{}", id);
        tagMapper.deleteById(id);
    }

    private void upRecursion(List<TagVO> tagVOList, Set<Long> idSet, int pointer) {
        Long id = tagVOList.get(pointer).getParentId();
        if (id != null) {
            TagQuery tagQuery = new TagQuery();
            tagQuery.setId(id);
            selectAndAddTagVO(tagVOList, idSet, tagQuery);
        }
        if (pointer + 1 < tagVOList.size()) {
            upRecursion(tagVOList, idSet, pointer + 1);
        }
    }


    private void downRecursion(List<TagVO> tagVOList, Set<Long> idSet, int pointer) {
        Long id = tagVOList.get(pointer).getId();
        if (id != null) {
            TagQuery tagQuery = new TagQuery();
            tagQuery.setParentId(id);
            selectAndAddTagVO(tagVOList, idSet, tagQuery);
        }
        if (pointer + 1 < tagVOList.size()) {
            downRecursion(tagVOList, idSet, pointer + 1);
        }
    }

    private void selectAndAddTagVO(List<TagVO> tagVOList, Set<Long> idSet, TagQuery tagQuery) {
        List<TagVO> tagVOListPlus = tagMapper.selectTagVOByTagQuery(tagQuery);
        addTagVO(tagVOList, idSet, tagVOListPlus);
    }

    private void addTagVO(List<TagVO> tagVOList, Set<Long> idSet, List<TagVO> tagVOListPlus) {
        if (tagVOListPlus != null && !tagVOListPlus.isEmpty()) {
            for (TagVO tagVO : tagVOListPlus) {
                if (tagVO != null && !idSet.contains(tagVO.getId())) {
                    tagVOList.add(tagVO);
                    idSet.add(tagVO.getId());
                }
            }
        }
    }

}
